﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using LibCommon;
using LibGUI.Schedule;
using LibRTC;
using LibRTC.Core;
using LibRTC.Core.MessageMap.MessagingEvent;
using LibRTC.Interface;
using RTCCore;

namespace LibGUI.Chat {
    public partial class ChatForm : BaseChatForm  //Form
    {
        private static ILogger LOGGER = LoggerFactory.GetLogger("ChatForm", null);

        private MetaDataChat _metaDataChat;
        private MessageDispatcher _messageDispatcher;
        private IRTCCoreOperations _rtcOperations;

        private IVideoWindow _receiveWindow;
        private IVideoWindow _previewWindow;

        public ChatForm(MetaDataChat data, MessageDispatcher messageDispatcher, IRTCCoreOperations operations)
        {
            _metaDataChat = data;
            _messageDispatcher = messageDispatcher;
            _rtcOperations = operations;

            InitializeComponent();
        }

        public IRTCSession GetIMSession() {
            return _metaDataChat.imSession;
        }

        public void SetIMSession(IRTCSession imsession)
        {
            _metaDataChat.imSession = imsession;
        }

        public IRTCSession GetVideoSession() {
            return _metaDataChat.videoSession;
        }

        public void SetVideoSession(IRTCSession videoSession)
        {
            _metaDataChat.videoSession = videoSession;
        }

        public void SetReceiveWindow(IVideoWindow window)
        {
            if (null == window)
            {
                // do nothing
                return;
            }

            Debug.Assert(null == _receiveWindow);
            _receiveWindow = window;

            _receiveWindow.WindowStyle = (int)(WindowsConst.WS_CHILD | WindowsConst.WS_CLIPCHILDREN |
                                               WindowsConst.WS_CLIPSIBLINGS);
            _receiveWindow.Owner = (int)labelRemoteVideo.Handle;
            _receiveWindow.SetWindowPosition(labelRemoteVideo.ClientRectangle.Left,
                                             labelRemoteVideo.ClientRectangle.Top,
                                             labelRemoteVideo.ClientRectangle.Width,
                                             labelRemoteVideo.ClientRectangle.Height);
            _receiveWindow.Visible = 1;
        }

        public void SetPreviewWindow(IVideoWindow window)
        {
            if(null == window) {
                // do nothing
                return;
            }

            Debug.Assert(null == _previewWindow);
            _previewWindow = window;

            _previewWindow.WindowStyle = (int)(WindowsConst.WS_CHILD | WindowsConst.WS_CLIPCHILDREN |
                                               WindowsConst.WS_CLIPSIBLINGS);
            _previewWindow.Owner = (int)labelLocalVideo.Handle;
            _previewWindow.SetWindowPosition(labelLocalVideo.ClientRectangle.Left, 
                                             labelLocalVideo.ClientRectangle.Top,
                                             labelLocalVideo.ClientRectangle.Width,
                                             labelLocalVideo.ClientRectangle.Height);
            _previewWindow.Visible = 1;

        }

        public void RemoveReceiveWindow()
        {
            if(null != _receiveWindow) {
                //_receiveWindow.Visible = 0;
                //_receiveWindow.Owner = 0;
                _receiveWindow = null;
            }
        }

        public void RemovePreviewWindow()
        {
            if(null != _previewWindow) {
                //_previewWindow.Visible = 0;
                //_previewWindow.Owner = 0;
                _previewWindow = null;
            }
        }

        public void DisplayMessage(string user, string messageHeader,string message)
        {
            listViewChatLog.Items.Add(user);
            listViewChatLog.Items.Add("    "+message);

            listViewChatLog.SelectedIndex = listViewChatLog.Items.Count - 1;
        }

        public void StopIMChat()
        {
            if (null != _metaDataChat.imSession) {
                IRTCSession imSession = _metaDataChat.imSession;
                _metaDataChat.imSession = null;

                if(RTC_SESSION_STATE.RTCSS_CONNECTED == imSession.State) {
                    imSession.Terminate(RTC_TERMINATE_REASON.RTCTR_NORMAL);
                }
            }
        }

        public void StopVideoChat()
        {
            if (null == _metaDataChat.videoSession)
            {
                LOGGER.LogError("There is no video session !");
                return;
            }

            RemovePreviewWindow();
            RemoveReceiveWindow();

            _metaDataChat.videoSession.Terminate(RTC_TERMINATE_REASON.RTCTR_NORMAL);
            _metaDataChat.videoSession = null;
        }
   
        private void buttonSendMessage_Click(object sender, EventArgs e)
        {
            if(0 == chatMessage.Text.Trim().Length)
            {
                // we do not send empty message
                return;
            }

            try
            {

                if (null == _metaDataChat.imSession || 
                    _metaDataChat.imSession.Participants.Count<= 1 ||
                    RTC_SESSION_STATE.RTCSS_CONNECTED != _metaDataChat.imSession.State)
                {
                    _metaDataChat.imSession = _rtcOperations.MakeCall(_metaDataChat.remoteUserURI, RTC_SESSION_TYPE.RTCST_IM);

                }

                _metaDataChat.imSession.SendMessage(null, chatMessage.Text, 0);

                //display the message
                DisplayMessage(_metaDataChat.localUserName, null,chatMessage.Text);               

                //clean the old message
                chatMessage.Text = string.Empty;
            }
            catch (Exception e1)
            {                
                LOGGER.LogError(e1.ToString());
            }

        }

        private void OnFormClose(object sender, FormClosingEventArgs e)
        {
            _messageDispatcher.RemoveChatForm(_metaDataChat.remoteUserURI);
            StopVideoChat();
            StopIMChat();
        }

        private void buttonStartVideo_Click(object sender, EventArgs e)
        {
            if(null != _metaDataChat.videoSession)
            {
                LOGGER.LogError("There is already an video session !");  
                return;
            }

            IRTCSession videoSession = _rtcOperations.MakeCall(_metaDataChat.remoteUserURI, RTC_SESSION_TYPE.RTCST_PC_TO_PC);
            if(null != videoSession)
            {
                _metaDataChat.videoSession = videoSession;
            }

            _messageDispatcher.SetVideoChatForm(this);
        }

        private void buttonStopVideo_Click(object sender, EventArgs e)
        {
            StopVideoChat();

            buttonStartVideo.Enabled = true;
            buttonStopVideo.Enabled = false;
        }

        public override void OnMessaging(string remoteUserName, string remoteUserURI, string messageHeader, string messageBody) {
            Debug.Assert(null != remoteUserName);
            Debug.Assert(null != remoteUserURI);
            Debug.Assert(null != messageHeader);
            Debug.Assert(null != messageBody);

            if(_metaDataChat.remoteUserURI.Equals(remoteUserURI)) {
                DisplayMessage(remoteUserName,messageHeader,messageBody);
            }
        }

        public override void OnUserStatus(string remoteUserName, string remoteUserURI, RTC_MESSAGING_USER_STATUS userStatus)
        {
            // right now, we do nothing
        }

        public override void OnSessionConnected(IRTCSession session)
        {
            Debug.Assert(null != session);      
            LOGGER.LogDebug("Session Connected : "+session.ToString());

            if(session == _metaDataChat.videoSession) {
                // enable/disable the corresponding buttons
                buttonStartVideo.Enabled = false;
                buttonStopVideo.Enabled = true;
            }

        }

        public override void OnSessionDisconnected(IRTCSession session)
        {
            Debug.Assert(null != session);
            LOGGER.LogDebug("Session Disconnected : " + session.ToString());

            if(session == _metaDataChat.imSession) {
                StopIMChat();
            }else if (session == _metaDataChat.videoSession) {
                StopVideoChat();

                buttonStartVideo.Enabled = true;
                buttonStopVideo.Enabled = false;
            }
            else {
                // We do nothing 
            }
        }
    }
}